#pragma once
#include <memory>
#include <vector>
#include <map>
#include <utility>

#include "types.hpp"
#include "Utils.hpp"

////////////////////////////////////////////////////////////////
// Operations
//
class CMob;
namespace Operations
{
	/// Interface of Operation
	class IOperation : public CProperty<IOperation, CMob>
	{
		friend class CMob; // for pMob

	public:
		static Container getParent();
		CMob* pMob;

	public:
		class Param;
		
	public:
		IOperation() {} ///< Constructor
		virtual ~IOperation(){} ///< Virtual destructor
		virtual void callExecuter(Param& param){}
		static void Execute(Param& param);
		virtual int process(Param& param){return 0;}

//		virtual static uint Id() = 0;
		virtual uint getId() const = 0;
		virtual void print() const = 0; /// Print operation

	};

	template<class T, class Base = IOperation>
	class IOperationProxy : public Base
	{
	public:
		typedef typename Base::Param Param;

	public:
		uint getId() const;
		void callExecuter(Param& param);
	};

	/// Operation - Move
	class CMove : public IOperationProxy<CMove>
	{
	public:
		/// Return velues
		enum
		{
			OK = 0,
			COLLISION = -1,
		};

	public:
		CMove(position_t t);

		position_t getPos() const { return to; }

		static uint Id() { return 10; }
		static void Execute(Param& param);
		void print() const;

	protected:
		CMove(){}
		
	protected:
		position_t to;
	};

	/// Operation - Attack
	class CAttack : public IOperationProxy<CAttack>
	{
	public:
		/// Return values
		enum
		{
			OK = 0,
			MISS = -1,
			DRAW = 1
		};
	public:
		CAttack(position_t position, uint damage);

		position_t getPos() const { return pos; }
		uint getDamage() const { return dmg; }

		static uint Id() { return 15; }
		static void Execute(Param& param);
		void print() const;

	protected:
		position_t pos;
		uint dmg;
	};

	/// Operation - Surface from Diving
	class CSurface : public IOperationProxy<CSurface, CMove>
	{
	public:
		static uint Id() { return 10000; }
		static void Execute(Param& param);
		int process(Param& param);
		void print() const;
	};

	/// Operation - Dive
	class CDive : public IOperationProxy<CDive, CMove>
	{
	public:
		/// Operation - Diving counter
		/// When count is 0, remove and surface
		class CDiveCounter
			: public IOperationProxy<CDiveCounter, CSurface>
		{
			enum
			{
				ABORT = 1
			};
		public:
			CDiveCounter(uint count);

			static uint Id() { return 9999; }
			static void Execute(Param& param);
			int process(Param& param);
			void print() const;
		
		private:
			uint c;
		};
		
	public:
		static uint Id() { return 90; }
		static void Execute(Param& param);
		int process(Param& param);
		void print() const;
	};

/*
	/// Operation - Search
	class CSearch
		: public IOperationProxy<IOperation, 3>
	{
		/// Operation - End of Searching(auto)
		class CSearchConclude
			: public IOperationProxy<IOperation, 90>
		{
		public:
			enum
			{
				OK = 0
			};
		public:
			CSearchConclude();

			int process(Param& param);
			void print() const;

		private:
			uint counter;
		};

	public:
		/// Return values
		enum
		{
			OK = 0;
		};
	public:
		int process(Param& param);
		void print() const;
	};
*/
}

typedef Operations::IOperation COperation;
typedef ptr_vector<COperation> COperations;

class CPlayers;
class CField;
/// Operationの実行管理
class RankedOperations
{
	class Impl;
	Impl* pImpl;

public:
	typedef std::vector<std::pair<COperation*, int> > result_info;

public:
	RankedOperations(CPlayers& players, CField& field);
	~RankedOperations();

	bool executeNextOperations();
	void assignResults(result_info& ri) const;

	void print() const;
};

